﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;



namespace ImageOperate.Controllers
{
    public class HomeController : Controller
    {
        #region 视图
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Image()
        {
            return View();
        }

        public ActionResult Image2()
        {
            return View();
        }
        #endregion

        [HttpPost]
        public JsonResult GetRegion()
        {
            // 读取请求体数据
            using (var reader = new StreamReader(Request.InputStream))
            {
                var jsonString = reader.ReadToEnd();
                var clickPoint = JsonConvert.DeserializeObject<ClickPoint>(jsonString);

                #region 处理 clickPoint 数据
                //加载图片
                string path = clickPoint.ImagePath == null ? "/Content/Images/pic.jpg" : clickPoint.ImagePath;
                #endregion
                string imagePath = Server.MapPath("~" + path);
                Bitmap image = new Bitmap(imagePath);

                //使用Flood Fill 算法查找空白区域
                RegionResult result = FindLargestBlankRegion(image, clickPoint.X, clickPoint.Y);

                return Json(result);
            }
        }

        private RegionResult FindLargestBlankRegion(Bitmap image, int startX, int startY)
        {
            Color emptyColor = Color.White;
            //假设白色区域为 255,255,255颜色，非白色区域为其他颜色
            int width = image.Width;
            int height = image.Height;

            //bool[,] visited = new bool[width, height];
            List<Point> regionPoints = new List<Point>();


            ////使用队列来实现Flood Fill
            //Queue<Point> queue = new Queue<Point>();
            //queue.Enqueue(new Point(startX, startY));
            //visited[startX, startY] = true;



            // 计算最大区域的四个顶点
            int minX = startX, maxX = startX, minY = startY, maxY = startY;

            #region 分别向四个方向扩展
            //向上扩展
            for (int i = startY; i >= 0; i--)
            {
                if (IsEmptyColor(image.GetPixel(startX, i), emptyColor))
                {
                    minY = i;
                    regionPoints.Add(new Point(startX, i));
                }
                else
                    break;
            }

            //向下扩展
            for (int i = startY; i < height; i++)
            {
                if (IsEmptyColor(image.GetPixel(startX, i), emptyColor))
                {
                    maxY = i;
                    regionPoints.Add(new Point(startX, i));
                }
                else
                    break;
            }

            //向左扩展
            for (int i = startX; i >= 0; i--)
            {
                if (IsEmptyColor(image.GetPixel(i, startY), emptyColor))
                {
                    minX = i;
                    regionPoints.Add(new Point(i, startY));
                }
                else
                    break;
            }

            //向右扩展
            for (int i = startX; i < width; i++)
            {
                if (IsEmptyColor(image.GetPixel(i, startY), emptyColor))
                {
                    maxX = i;
                    regionPoints.Add(new Point(i, startY));
                }
                else
                    break;
            }
            #endregion

            //计算扩展的矩形区域
            int areaWidth = maxX - minX;
            int areaHeight = maxY - minY;
            int pixelArea = areaWidth * areaHeight;

            #region
            ////四个方向的偏移量
            //int[] dx = { -1, 1, 0, 0 };
            //int[] dy = { 0, 0, -1, 1 };

            //while (queue.Count > 0)
            //{
            //    Point current = queue.Dequeue();
            //    int x = current.X;
            //    int y = current.Y;


            //    //如果当前位置是空白区域，加入到区域中
            //    if (IsBlank(image.GetPixel(x, y)))
            //    {
            //        regionPoints.Add(new Point(x, y));

            //        //扩展四个方向
            //        for (int i = 0; i < 4; i++)
            //        {
            //            int newX = x + dx[i];
            //            int newY = y + dy[i];

            //            if (newX >= 0 && newX < width && newY >= 0 && newY < height && !visited[newX, newY] && IsBlank(image.GetPixel(newX, newY)))
            //            {

            //                //只在像素是空白色时才扩展
            //                if (IsEmptyColor(image.GetPixel(newX, newY), emptyColor))
            //                {

            //                    visited[newX, newY] = true;
            //                    //queue.Equals(new Point(newX, newY));
            //                    queue.Enqueue(new Point(newX, newY));

            //                    //更新扩展区域的顶点坐标
            //                    minX = Math.Min(minX, newX);
            //                    minY = Math.Min(minY, newY);
            //                    maxX = Math.Max(maxX, newX);
            //                    maxY = Math.Max(maxY, newY);
            //                }
            //                else
            //                {
            //                    break;
            //                }
            //            }
            //        }
            //    }
            //}

            #endregion


            var vertices = new List<Point>{
                new Point(startX,startY),
                new Point(minX,minY),
                new Point(maxX,maxY),
            };


            return new RegionResult
            {
                Count = regionPoints.Count,
                Width = areaWidth,
                Height = areaHeight,
                Area = pixelArea,
                Vertices = vertices
            };


        }


        [HttpPost]
        public JsonResult ProcessClick(int x, int y, string imagePath)
        {
            //加载图片
            string imagePathWithFullPath = Server.MapPath("~/Content/images/" + imagePath);
            Bitmap bitmap = new Bitmap(imagePathWithFullPath);

            //获取点击点颜色
            //Color clickColor = bitmap.GetPixel(x, y);
            Color color = Color.White;

            //执行扩展逻辑，找到矩形区域
            var expandedArea = GetExpandedArea(bitmap, x, y, color);

            return Json(new
            {
                x = x,
                y = y,
                expandedArea = expandedArea
            });
        }


        private object GetExpandedArea(Bitmap bitmap, int startX, int startY, Color baseColor)
        {
            int width = bitmap.Width;
            int height = bitmap.Height;

            //初始化矩形区域
            int minX = startX, minY = startY, maxX = startX, maxY = startY;

            //向上扩展
            for (int i = startY; i >= 0; i--)
            {
                if (IsEmptyColor(bitmap.GetPixel(startX, i), baseColor))
                {
                    minY = i;
                }
                else
                {
                    break;
                }
            }

            //向下扩展
            for (int i = startY; i < height; i++)
            {
                if (IsEmptyColor(bitmap.GetPixel(startX, i), baseColor))
                {
                    maxY = i;
                }
                else
                {
                    break;
                }
            }

            //向左扩展
            for (int i = startX; i >= 0; i--)
            {
                if (IsEmptyColor(bitmap.GetPixel(i, startY), baseColor))
                {
                    minX = i;
                }
                else
                {
                    break;
                }
            }

            //向右扩展
            for (int i = startX; i < width; i++)
            {
                if (IsEmptyColor(bitmap.GetPixel(i, startY), baseColor))
                {
                    maxX = i;
                }
                else
                {
                    break;
                }
            }

            //计算扩展的矩形区域
            int areaWidth = maxX - minX;
            int areaHeight = maxY - minY;
            int pixelCount = areaWidth * areaHeight;

            return new
            {
                topLeft = new { X = minX, Y = minY },
                bottomRight = new { X = maxX, Y = maxY },
                width = areaWidth,
                height = areaHeight,
                pixelCount = pixelCount
            };

        }


        #region 公共方法
        private bool IsSameColor(Color color1, Color color2)
        {
            //比较颜色是否相同，容忍一定的误差
            return color1.R == color2.R && color1.G == color2.G && color1.B == color2.B;
        }

        /// <summary>
        /// 定义颜色比较函数，比较ARGB值是否相等
        /// </summary>
        /// <param name="color"></param>
        /// <param name="emptyColor"></param>
        /// <returns></returns>
        bool IsEmptyColor(Color color, Color emptyColor)
        {
            return color.ToArgb() == emptyColor.ToArgb();
        }

        /// <summary>
        /// 判断是否为空白区域（根据像素颜色判断，这里假设白色为 255,255,255
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        private bool IsBlank(Color color)
        {
            return color.R == 255 && color.G == 255 && color.B == 255;
        }
        #endregion

        #region Model
        public class RegionResult
        {
            public int Width { get; set; }
            public int Height { get; set; }
            public int Count { get; set; }
            public int Area { get; set; }
            public List<Point> Vertices { get; set; }
        }

        public class ClickPoint
        {
            public int X { get; set; }
            public int Y { get; set; }
            public string ImagePath { get; set; }
        }
        #endregion

        #region 上传图片
        [HttpPost]
        public ActionResult UploadImage(HttpPostedFileBase file)
        {
            if (file != null && file.ContentLength > 0)
            {
                string date = DateTime.Now.Ticks.ToString();
                // Define the directory to save the uploaded file
                var path = Path.Combine(Server.MapPath("~/Content/Upload"), date + "_" + file.FileName);

                // Save the file to the server
                file.SaveAs(path);

                // Return the relative path of the saved file
                return Json(new { success = true, imagePath = "/Content/Upload/" + date + "_" + file.FileName });
            }

            return Json(new { success = false, message = "No file uploaded." });
        }
        #endregion
    }
}